package com.zhdl.hardware.plc.siemens.repository.impl;

import cn.hutool.core.util.HexUtil;
import com.google.common.eventbus.Subscribe;
import com.project.command.faq.event.behavior.BehaviorPerform;
import com.project.command.instruction.strategy.process.data.AfterStrategyParam;
import com.zhdl.common.ytools.BaseConversionTools;
import com.zhdl.common.ytools.callback.CommonCallback;
import com.zhdl.common.ytools.eventbus.center.EventBusCenter;
import com.zhdl.hardware.plc.siemens.repository.SiemensCmdHandleDao;
import com.zhdl.network.other_protocol.modbusrtu.dto.ModbusDto;
import com.zhdl.network.other_protocol.modbusrtu.request.WriteSingleKeepRegisterReq;
import com.zhdl.network.other_protocol.modbustcp.ModbusTcpRespPkg;
import com.zhdl.network.strategy.common.ProtocolContext;
import com.zhdl.network.strategy.modbusrtu.ModbusRtuStrategy;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class SiemensCmdHandleDaoImpl implements SiemensCmdHandleDao {

    /**
     * PLC西门子-网口
     */
    public String port;
    /**
     * 通信协议处理
     */
    public ProtocolContext protocolContext;
    /**
     * Callback 回调管理
     */
    public Map<String, CommonCallback<String>> commonCallbackMap = new ConcurrentHashMap<>();

    public SiemensCmdHandleDaoImpl(String port, BehaviorPerform behaviorPerform) {
        EventBusCenter.getEventBus().register(this);
        protocolContext = new ProtocolContext(new ModbusRtuStrategy(port, behaviorPerform));
        this.port = port;
    }

    @Subscribe
    public void dataReception(AfterStrategyParam event) {
        /* 策略判断-判断当前串口 */
        if (port.equals(event.getPortKey())) {
            /* 获取电机指令返回的数据 */
            //此处接收串口或网口客户端回应代码,并处理
            List<ModbusDto> list = event.getNewData();
            ModbusDto modbusDto = list.get(0);
            String instruction = event.getInstruction();
            instruction = instruction.replaceAll(" ", "");
            instruction = instruction.toLowerCase();
            for (String cmd : commonCallbackMap.keySet()) {
                cmd = cmd.toLowerCase();
                if (cmd.contains(instruction)) {
                    commonCallbackMap.get(cmd).statusCallback(HexUtil.encodeHexStr(modbusDto.getUnitBuff()));
                    commonCallbackMap.remove(cmd);
                }

            }
        }
    }

    /**
     * 读取plc的值 -03
     *
     * @param address  寄存器地址
     * @param count    寄存器个数
     * @param callback 回调
     */
    @Override
    public void raedValueByAddress(String address, int count, CommonCallback<String> callback) {
        raedValueByAddress("01", address, count, callback);
    }

    /**
     * 写入plc的值 - 06
     *
     * @param address 寄存器地址
     * @param value   寄存器值
     */
    @Override
    public void writeValueByAddress(String address, String value) {
        writeValueByAddress("01", address, value);
    }

    /**
     * 写入plc的值 - 10
     *
     * @param address 寄存器地址
     * @param value   寄存器值
     */
    @Override
    public void writeValuesByAddress(String address, String value) {
        writeValuesByAddress("01", address, value);
    }

    /**
     * 读取plc的值
     *
     * @param address  寄存器地址
     * @param count    寄存器个数
     * @param callback 回调
     */
    @Override
    public void raedValueByAddress(String slaveId, String address, int count, CommonCallback<String> callback) {
        WriteSingleKeepRegisterReq writeSingleKeepRegisterReq = new WriteSingleKeepRegisterReq();
        writeSingleKeepRegisterReq.setId(slaveId);
        writeSingleKeepRegisterReq.setStartAddress(address);
        writeSingleKeepRegisterReq.setWriteValue(BaseConversionTools.intToShortHex(count));
        try {
            byte[] bytes = ModbusTcpRespPkg.ReadKeepRegister(writeSingleKeepRegisterReq);
            String cmd = HexUtil.encodeHexStr(bytes);
            protocolContext.sendCmd(cmd);
            commonCallbackMap.put(cmd, callback);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 写入plc的值
     *
     * @param address 寄存器地址
     * @param value   寄存器值
     */
    @Override
    public void writeValueByAddress(String slaveId, String address, String value) {
        WriteSingleKeepRegisterReq writeSingleKeepRegisterReq = new WriteSingleKeepRegisterReq();
        writeSingleKeepRegisterReq.setId(slaveId);
        writeSingleKeepRegisterReq.setStartAddress(address);
        writeSingleKeepRegisterReq.setWriteValue(value);
        try {
            byte[] bytes = ModbusTcpRespPkg.WriteSingleKeepRegister(writeSingleKeepRegisterReq);
            String cmd = HexUtil.encodeHexStr(bytes);
            protocolContext.sendCmd(cmd);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 写入plc的值
     *
     * @param address 寄存器地址
     * @param value   寄存器值
     */
    @Override
    public void writeValuesByAddress(String slaveId, String address, String value) {
        WriteSingleKeepRegisterReq writeSingleKeepRegisterReq = new WriteSingleKeepRegisterReq();
        writeSingleKeepRegisterReq.setId(slaveId);
        writeSingleKeepRegisterReq.setStartAddress(address);
        writeSingleKeepRegisterReq.setWriteValue(value);
        try {
            byte[] bytes = ModbusTcpRespPkg.WriteManyKeepRegister(writeSingleKeepRegisterReq, 1);
            String cmd = HexUtil.encodeHexStr(bytes);
            protocolContext.sendCmd(cmd);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
